package com.alks.function.download;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.excelUtils.FreezeTopRowsHandler;
import com.alks.common.utils.export.dto.MockMultipartFile;
import com.alks.common.utils.export.service.FileExportTask;
import com.alks.entity.data.entity.PcLotDetail;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.vo.biocontrol.deptwork.ReportStitchDailyVO;
import com.alks.function.data.vo.biocontrol.deptwork.ReportStitchDailyVO2;
import com.alks.function.handler.excel.ReportMonthCXHandler;
import com.alks.function.handler.excel.ReportStitchDailyStyleHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author MS
 * @since 2025/2/19上午10:39
 */
@Slf4j
public class StitchStkExport extends FileExportTask {
    private final List<ReportStitchDailyVO2> stitchList;
    private final List<PcLotDetail> lotDetailList;

    public StitchStkExport(List<ReportStitchDailyVO2> stitchList, List<PcLotDetail> lotDetailList) {
        super();
        this.stitchList = stitchList;
        this.lotDetailList = lotDetailList;
    }

    @Override
    protected MockMultipartFile generateFile(String fileName) throws Exception {
        MockMultipartFile multipartFile = null;
        Map<String, List<PcLotDetail>> lotMap = lotDetailList.stream().collect(Collectors.groupingBy(PcLotDetail::getLotNo));
        int maxSize = 0;
        /*封装数据*/
        List<ReportStitchDailyVO> voList = new ArrayList<>(stitchList.size());
        for (ReportStitchDailyVO2 stitch : stitchList) {
            List<PcLotDetail> detailList = lotMap.get(stitch.getLotNo());
            if (ArrayUtils.isEmpyt(detailList)){
                continue;
            }
            ReportStitchDailyVO vo = new ReportStitchDailyVO();
            vo.setDeptName(stitch.getDeptName());
            vo.setLotNo(stitch.getLotNo());
            detailList = detailList.stream()
                    .sorted(Comparator.comparingDouble(pcLotDetail -> Double.parseDouble(pcLotDetail.getSizeNo())))
                    .collect(Collectors.toList());
            for (int i = 0; i < detailList.size(); i++) {
                String sizeNo = detailList.get(i).getSizeNo();
                /*直接用满参构造添加数据*/
                vo.getPoList().add(sizeNo);
                long orderQty = detailList.get(i).getOrderQty()==0?0:detailList.get(i).getOrderQty().longValue();
                long surplusQty = detailList.get(i).getSurplusQty()==null?0:detailList.get(i).getSurplusQty().longValue();
                vo.getOrderList().add(new ReportStitchDailyVO.PoData(sizeNo, orderQty));
                vo.getPrefixList().add(new ReportStitchDailyVO.PoData(sizeNo, surplusQty));
                int qtyIndex = i + 1;
                String qtyFieldName = "qty" + qtyIndex;
                String dailyQtyFieldName = "dailyQty" + qtyIndex;
                try {
                    /*获取总入库数量*/
                    Field field = ReportStitchDailyVO2.class.getDeclaredField(qtyFieldName);
                    Field dailyField = ReportStitchDailyVO2.class.getDeclaredField(dailyQtyFieldName);
                    field.setAccessible(true);
                    dailyField.setAccessible(true);
                    long qty = ((Float)field.get(stitch)).longValue();
                    long dailyQty = ((Float)dailyField.get(stitch)).longValue();
                    long shortQty = orderQty + surplusQty - qty;
                    vo.getAggregateList().add(new ReportStitchDailyVO.PoData(sizeNo, qty));
                    vo.getOweList().add(new ReportStitchDailyVO.PoData(sizeNo, shortQty));
                    vo.getDailyList().add(new ReportStitchDailyVO.PoData(sizeNo, dailyQty));
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    log.error("\n错误接口：stitchStkExportQuery\n错误原因：反射异常，字段名：{}或{}\n{}",qtyFieldName,dailyQtyFieldName,e.getMessage(),e);
                    throw new ServiceErrorException("程序异常");
                }
            }
            if (vo.getPoList().size() > maxSize) {
                maxSize = vo.getPoList().size();
            }
            vo.setTotal(detailList.stream()
                    .mapToLong(a->{
                        long orderQty = a.getOrderQty() == null ? 0 : a.getOrderQty().longValue();
                        long surplusQty = a.getSurplusQty() == null ? 0 : a.getSurplusQty().longValue();
                        return orderQty+surplusQty;
                    })
                    .filter(Objects::nonNull).sum());
            voList.add(vo);
        }
        int rowIndex = 0;
        // 需要合并数据的行
        List<Integer> mergeRowIndex = new ArrayList<>();
        // 固定列
        String[] fixation = {"指令", "总数", "配码", "合计"};
        // 总列数
        int totalColumn = maxSize + fixation.length;
        List<List<String>> dataList = new ArrayList<>();
        // 添加表头数据
        dataList.add(Collections.nCopies(totalColumn, fileName));
        String dataStr = LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd");
        dataList.add(Collections.nCopies(totalColumn, "日期：" + dataStr));
        mergeRowIndex.add(rowIndex++);
        mergeRowIndex.add(rowIndex++);
        // 动态生成数据
        boolean tag = false;
        for (ReportStitchDailyVO dailyVO : voList) {
            List<String> d1 = new ArrayList<>(Arrays.asList(fixation));
            List<String> d2 = new ArrayList<>(Arrays.asList(fixation));

            // 插入动态列数据
            for (int i = 0; i < maxSize; i++) {
                d1.add(fixation.length - 1, dailyVO.getDeptName());
                if (i < dailyVO.getPoList().size()) {
                    d2.add(d2.size() - 1, dailyVO.getPoList().get(i));
                } else {
                    d2.add(d2.size() - 1, null);
                }
            }
            if (!tag) {
                d1.add("备注");
                tag = true;
            } else {
                d1.add("");
            }
            d2.add(null);
            dataList.add(d1);
            dataList.add(d2);
            dataList.add(data2List("订单数", dailyVO, dailyVO.getOrderList(), maxSize));
            dataList.add(data2List("预补数", dailyVO, dailyVO.getPrefixList(), maxSize));
            dataList.add(data2List("当日入库", dailyVO, dailyVO.getDailyList(), maxSize));
            dataList.add(data2List("累计入库", dailyVO, dailyVO.getAggregateList(), maxSize));
            dataList.add(data2List("欠数", dailyVO, dailyVO.getOweList(), maxSize));
            mergeRowIndex.add(rowIndex);
            mergeRowIndex.add(rowIndex + 1);
            rowIndex += 7; // 每7行为一组
        }
        // 定义需要合并的列
        int[] mergeColumnIndex = {0, 1, 2, totalColumn - 1};
        ExcelWriter excelWriter = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            excelWriter = EasyExcel.write(outputStream)
                    .registerWriteHandler(new ReportStitchDailyStyleHandler(mergeColumnIndex, mergeRowIndex.stream().mapToInt(Integer::intValue).toArray(), 2))
                    .registerWriteHandler(new FreezeTopRowsHandler(0, 2))
                    .build();
            excelWriter.write(dataList, EasyExcel.writerSheet(0, fileName).build());
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            //关闭流
            assert excelWriter != null;
            excelWriter.finish();
            multipartFile = new MockMultipartFile(fileName, fileName, MediaType.MULTIPART_FORM_DATA_VALUE, new ByteArrayInputStream(outputStream.toByteArray()));
            outputStream.close();
        }
        return multipartFile;
    }

    private List<String> data2List(String name, ReportStitchDailyVO dailyVO, List<ReportStitchDailyVO.PoData> dataList, int maxSize) {
        List<String> vd1 = new ArrayList<>();
        vd1.add(dailyVO.getLotNo());
        vd1.add(String.valueOf(dailyVO.getTotal()));
        vd1.add(name);
        Map<String, Long> dataMap = dataList.stream().collect(Collectors.toMap(ReportStitchDailyVO.PoData::getSizeNo, ReportStitchDailyVO.PoData::getQty));
        for (int i = 0; i < maxSize; i++) {
            if (i < dailyVO.getPoList().size()) {
                String po = dailyVO.getPoList().get(i);
                if (dataMap.containsKey(po)){
                    vd1.add(String.valueOf(dataMap.get(po)));
                } else {
                    vd1.add(null);
                }
            } else {
                vd1.add(null);
            }
        }
        vd1.add(String.valueOf(dataList.stream().mapToLong(ReportStitchDailyVO.PoData::getQty).sum()));
        vd1.add(null);
        return vd1;
    }
}
